let socket = null
let isConnected = false
let reconnectAttempts = 0
const maxReconnectAttempts = 10
let reconnectTimer = null

const subscribers = new Set()

function getWsUrl() {
  const base = import.meta.env.VITE_APP_BASE_API || '/dev-api'
  const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'
  // 注意：按你的网关配置，外部路径需要以 /Chat 开头，网关 StripPrefix=1 后端点仍为 /chat/{userName}
  return `${protocol}//${location.host}${base}/Chat/chat/kefu`
}

function notifySubscribers(event) {
  subscribers.forEach((fn) => {
    try { fn(event) } catch (e) { /* ignore */ }
  })
}

function connectInternal() {
  try {
    const url = getWsUrl()
    socket = new WebSocket(url)

    socket.onopen = () => {
      isConnected = true
      reconnectAttempts = 0
      notifySubscribers({ type: 'open' })
    }

    socket.onmessage = (evt) => {
      const text = typeof evt.data === 'string' ? evt.data : ''
      notifySubscribers({ type: 'message', data: text })
    }

    socket.onclose = () => {
      isConnected = false
      notifySubscribers({ type: 'close' })
      if (reconnectAttempts < maxReconnectAttempts) {
        const delay = Math.min(1000 * (reconnectAttempts + 1), 5000)
        reconnectAttempts++
        clearTimeout(reconnectTimer)
        reconnectTimer = setTimeout(connectInternal, delay)
      }
    }

    socket.onerror = () => {
      // handled by onclose
    }
  } catch (e) {
    // ignore
  }
}

export function ensureConnected() {
  if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) {
    return
  }
  connectInternal()
}

export function sendMessage(text) {
  if (!socket || socket.readyState !== WebSocket.OPEN) return false
  try { socket.send(text); return true } catch { return false }
}

export function closeConnection() {
  try { clearTimeout(reconnectTimer); socket && socket.close() } catch {}
}

export function subscribe(handler) {
  subscribers.add(handler)
  return () => subscribers.delete(handler)
}

export function connectionState() {
  return { isConnected, attempts: reconnectAttempts }
}